package com.zzld.core.generator;

import java.util.ArrayList;
import java.util.List;

import org.mybatis.generator.api.GeneratedJavaFile;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.DefaultJavaFormatter;
import org.mybatis.generator.api.dom.java.Field;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.Interface;
import org.mybatis.generator.api.dom.java.JavaVisibility;
import org.mybatis.generator.api.dom.java.TopLevelClass;
import org.mybatis.generator.internal.util.StringUtility;

/**
 * 
 * @ClassName: MybatisServicePlugin
 * @Description: TODO
 * @author: 张楠 
 * @date: 2015年4月26日 上午10:33:34
 */
public class MybatisServicePlugin extends PluginAdapter {

	private FullyQualifiedJavaType slf4jLogger;
	private FullyQualifiedJavaType slf4jLoggerFactory;
	private FullyQualifiedJavaType serviceType;
	private FullyQualifiedJavaType daoType;
	private FullyQualifiedJavaType interfaceType;
	private FullyQualifiedJavaType superInterface;
	private FullyQualifiedJavaType superInterfaceImpl;
	private FullyQualifiedJavaType pojoType;
	private FullyQualifiedJavaType autowired;
	private FullyQualifiedJavaType service;
	
	private String baseService; 
	private String baseServiceImpl;
	private String servicePack;
	private String serviceImplPack;
	private String project;
	private String pojoUrl;
	
	boolean hasSuper=false;
	boolean hasSuperImpl=false;

	/**
	 * 是否添加注解
	 */
	private boolean enableAnnotation = true;

	public MybatisServicePlugin() {
		super();
		// 默认是slf4j
		slf4jLogger = new FullyQualifiedJavaType("org.slf4j.Logger");
		slf4jLoggerFactory = new FullyQualifiedJavaType("org.slf4j.LoggerFactory");
	}

	@Override
	public boolean validate(List<String> warnings) {
		if (StringUtility.stringHasValue(properties.getProperty("enableAnnotation"))){
			enableAnnotation = StringUtility.isTrue(properties.getProperty("enableAnnotation"));
		}
		//标识是否有基础service
		if (StringUtility.stringHasValue(properties.getProperty("baseServicePackage"))){
			hasSuper=true;
			baseService=properties.getProperty("baseServicePackage");
		}
		//标识是否有基础serviceimp
		if (StringUtility.stringHasValue(properties.getProperty("baseServiceImplPackage"))){
			hasSuperImpl=true;
			baseServiceImpl=properties.getProperty("baseServiceImplPackage");
		}
	
		servicePack = properties.getProperty("targetPackage");
		serviceImplPack = properties.getProperty("implPackage");
		project = properties.getProperty("targetProject");
		pojoUrl = context.getJavaModelGeneratorConfiguration().getTargetPackage();
		
		if (enableAnnotation) {
			autowired = new FullyQualifiedJavaType("org.springframework.beans.factory.annotation.Autowired");
			service = new FullyQualifiedJavaType("org.springframework.stereotype.Service");
		}
		
		return true;
	}

	@Override
	public List<GeneratedJavaFile> contextGenerateAdditionalJavaFiles(IntrospectedTable introspectedTable) {
		List<GeneratedJavaFile> files = new ArrayList<GeneratedJavaFile>();
		String table = introspectedTable.getBaseRecordType();
		String tableName = table.replaceAll(this.pojoUrl + ".", "");
		
		if(hasSuper){
			superInterface = new FullyQualifiedJavaType(baseService+"<"+tableName+">"); 
		}
		if(hasSuperImpl){
			superInterfaceImpl = new FullyQualifiedJavaType(baseServiceImpl+"<"+tableName+">"); 
		}
		
		//interfaceType = new FullyQualifiedJavaType("com.zzld.core.service.BaseServiceImpl<"+tableName+">");
		
		// mybatis
		daoType = new FullyQualifiedJavaType(introspectedTable.getMyBatis3JavaMapperType());
		interfaceType = new FullyQualifiedJavaType(servicePack + ".I" + tableName + "Service");
		serviceType = new FullyQualifiedJavaType(serviceImplPack + "." + tableName + "ServiceImpl");
		pojoType = new FullyQualifiedJavaType(pojoUrl + "." + tableName);
		
		Interface Iserviceinterface = new Interface(interfaceType);
		TopLevelClass topLevelClass = new TopLevelClass(serviceType);
		// 导入必要的类
		addImport(Iserviceinterface, topLevelClass);
		// 接口
		addService(Iserviceinterface,introspectedTable, tableName, files);
		// 实现类
		addServiceImpl(topLevelClass,introspectedTable, tableName, files);
		//日志
		addLogger(topLevelClass);
		return files;
	}

	/**
	 * 添加接口
	 * 
	 * @param tableName
	 * @param files
	 */
	protected void addService(Interface interface1,IntrospectedTable introspectedTable, String tableName, List<GeneratedJavaFile> files) {
		interface1.setVisibility(JavaVisibility.PUBLIC);
		if(hasSuper){
			interface1.addSuperInterface(superInterface);
		}
		
		// 生成文件
		DefaultJavaFormatter dfjf=new DefaultJavaFormatter();
		dfjf.getFormattedContent(interface1);
		GeneratedJavaFile file = new GeneratedJavaFile(interface1, project, dfjf);
		files.add(file);
		
	}

	/**
	 * 添加实现类
	 * 
	 * @param introspectedTable
	 * @param tableName
	 * @param files
	 */
	protected void addServiceImpl(TopLevelClass topLevelClass,IntrospectedTable introspectedTable, String tableName, List<GeneratedJavaFile> files) {
		topLevelClass.setVisibility(JavaVisibility.PUBLIC);
		if(hasSuperImpl){
			//继承接口
			topLevelClass.setSuperClass(superInterfaceImpl);
		}
		// 设置实现的接口
		topLevelClass.addSuperInterface(interfaceType);
		if (enableAnnotation) {
			topLevelClass.addAnnotation("@Service");
			topLevelClass.addImportedType(service);
		}
		// 添加引用dao
		addField(topLevelClass, tableName);
		// 生成文件
		DefaultJavaFormatter dfjf=new DefaultJavaFormatter();
		dfjf.getFormattedContent(topLevelClass);
		GeneratedJavaFile file = new GeneratedJavaFile(topLevelClass, project, dfjf);
		files.add(file);
	}

	/**
	 * 添加字段
	 * 
	 * @param topLevelClass
	 */
	protected void addField(TopLevelClass topLevelClass, String tableName) {
		// 添加 dao
		Field field = new Field();
		field.setName(toLowerCase(daoType.getShortName())); // 设置变量名
		topLevelClass.addImportedType(daoType);
		field.setType(daoType); // 类型
		field.setVisibility(JavaVisibility.PRIVATE);
		if (enableAnnotation) {
			field.addAnnotation("@Autowired");
		}
		topLevelClass.addField(field);
	}

	/**
	 * BaseUsers to baseUsers
	 * 
	 * @param tableName
	 * @return
	 */
	protected String toLowerCase(String tableName) {
		StringBuilder sb = new StringBuilder(tableName);
		sb.setCharAt(0, Character.toLowerCase(sb.charAt(0)));
		return sb.toString();
	}

	/**
	 * BaseUsers to baseUsers
	 * 
	 * @param tableName
	 * @return
	 */
	protected String toUpperCase(String tableName) {
		StringBuilder sb = new StringBuilder(tableName);
		sb.setCharAt(0, Character.toUpperCase(sb.charAt(0)));
		return sb.toString();
	}

	/**
	 * 导入需要的类
	 */
	private void addImport(Interface interfaces, TopLevelClass topLevelClass) {
		interfaces.addImportedType(pojoType);
		if(hasSuper){
			interfaces.addImportedType(superInterface);
		}
		topLevelClass.addImportedType(daoType);
		topLevelClass.addImportedType(interfaceType);
		topLevelClass.addImportedType(pojoType);
		topLevelClass.addImportedType(slf4jLogger);
		topLevelClass.addImportedType(slf4jLoggerFactory);
		if(hasSuperImpl){
			//继承接口
			topLevelClass.addImportedType(superInterfaceImpl);
		}
		
		if (enableAnnotation) {
			topLevelClass.addImportedType(service);
			topLevelClass.addImportedType(autowired);
		}
	}

	/**
	 * 导入logger
	 */
	private void addLogger(TopLevelClass topLevelClass) {
		Field field = new Field();
		field.setFinal(true);
		field.setInitializationString("LoggerFactory.getLogger(" + topLevelClass.getType().getShortName() + ".class)"); // 设置值
		field.setName("logger"); // 设置变量名
		field.setStatic(true);
		field.setType(new FullyQualifiedJavaType("Logger")); // 类型
		field.setVisibility(JavaVisibility.PRIVATE);
		topLevelClass.addField(field);
	}
}
